import java.net.*;
import java.io.*;
/*
 * @author HuGo LouReNCo 100915
 */
public class Servidor {

	public static void main(String[] args) {

		// porta do servidor
		int portaServidor;
		// padrao porta 60988
		portaServidor = 60988;
		if (args.length > 1) {
			try {
				portaServidor = Integer.parseInt(args[1]);
			} catch (NumberFormatException e) {
				System.out.println("NFE :" + e.getMessage());
			}
		}

		try {
			// criando socket servidor para conexoes
			ServerSocket listenSocket;
			listenSocket = new ServerSocket(portaServidor);

			do {
				// esperando conexoes de clientes
				System.out.println("Servidor aguardando conexoes do(s) cliente(s)...");
				Socket clientSocket;
				clientSocket = listenSocket.accept();
				new Connection(clientSocket);
			} while (true);
		} catch (IOException e) {
			System.out.println("Listen :" + e.getMessage());
		}
	}
}

class Connection extends Thread {

	DataInputStream entrada;
	DataOutputStream saida;
	Socket clientSocket;
	String tipoRequisicao;
	String nomeDoArquivo;
	long tamanhoDoArquivo;

	public Connection(Socket aClientSocket) {
		// TODO Auto-generated constructor stub
		try {
			// pegar os streams Input e Output
			clientSocket = aClientSocket;
			entrada = new DataInputStream(clientSocket.getInputStream());
			saida = new DataOutputStream(clientSocket.getOutputStream());

			this.start();

		} catch (IOException e) {
			System.out.println("Connection: " + e.getMessage());
		}
	}

	/**
	 * @param args
	 */
	public void run() {
		// TODO Auto-generated method stub
		try {
			tipoRequisicao = entrada.readUTF();
			if (tipoRequisicao.equals("PUT")) {
				System.out.println("Processando Requisicao = PUT");
				nomeDoArquivo = entrada.readUTF();
				tamanhoDoArquivo = entrada.readLong();
				System.out.println("Processando arquivo: " + nomeDoArquivo
						+ " - " + tamanhoDoArquivo + " bytes.");

				FileOutputStream saidaArquivo = new FileOutputStream(
						nomeDoArquivo);

				// recebendo e salvando arquivo do cliente
				byte[] buffer = new byte[4096];
				int tamanho;
				while ((tamanho = entrada.read(buffer)) != -1) {
					System.out.println("salvando... " + tamanho);
					saidaArquivo.write(buffer, 0, tamanho);
				}
				// liberando canal
				saidaArquivo.flush();
				// fechando conexoes
				saidaArquivo.close();
				saida.close();
				entrada.close();
				System.out.println("Cliente atendido. Ok!");

			} else if (tipoRequisicao.equals("GET")) {
				System.out.println("Processando Requisicao GET");
				File arquivo;
				arquivo = new File("1MB.pdf");
				FileInputStream entradaFIS = new FileInputStream(arquivo);

				// mede o tempo inicio
				long tempoInicio = System.currentTimeMillis();

				// enviando dados para o servidor
				System.out.println("Transferindo o arquivo: "
						+ arquivo.getName());
				saida.writeUTF(arquivo.getName());
				saida.writeLong(arquivo.length());

				byte[] buffer = new byte[4096];
				int tamanho;
				while ((tamanho = entradaFIS.read(buffer)) != -1) {
					saida.write(buffer, 0, tamanho);
				}

				// mede o tempo inicio
				long tempoFim = System.currentTimeMillis();
				double tempo = (tempoFim - tempoInicio) / 1000;

				// liberando canal de conexao
				saida.flush();
				saida.close();
				entrada.close();
				
				// arquivo enviado
				System.out.print("\nTransferencia concluida.\nTaxa: ");
				System.out.printf("%.3f", tempo);

			} else {
				System.out.println("Tipo de requisicao desconhecido.");
			}

		} catch (EOFException e) {
			System.out.println("EOF:" + e.getMessage());
		} catch (IOException e) {
			System.out.println("IOF:" + e.getMessage());
		} finally {
			try {
				System.out.println("\nSocket Fechado!");
				// fecha conexao do socket
				clientSocket.close();

			} catch (IOException e) {
				System.out.println("Falha ao fechar a conexao.");
			}
		}
	}
}
